package com.hljcert.data.service.system.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.hljcert.data.service.common.config.BusinessException;
import com.hljcert.data.service.common.config.StatusEnum;
import com.hljcert.data.service.common.result.CommonConstant;
import com.hljcert.data.service.system.entity.SysPermission;
import com.hljcert.data.service.system.mapper.SysPermissionMapper;
import com.hljcert.data.service.system.vo.TreeModel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.*;

/**
 * <p>
 * 菜单权限表 服务实现类
 * </p>
 */
@Service
public class SysPermissionService {

    @Resource
    private SysPermissionMapper sysPermissionMapper;

    public SysPermission getOne(LambdaQueryWrapper<SysPermission> query){
        return this.sysPermissionMapper.selectOne(query);
    }

    public List<SysPermission> list(LambdaQueryWrapper<SysPermission> query){
        return this.sysPermissionMapper.selectList(query);
    }

    public List<TreeModel> queryListByParentId(String parentId) {
        return sysPermissionMapper.queryListByParentId(parentId);
    }

    /**
     * 真实删除
     */
    @Transactional
    public void deletePermission(String id)  {
        SysPermission sysPermission = this.sysPermissionMapper.selectById(id);
        String pid = sysPermission.getParentId();
        if (StringUtils.isNotBlank(pid)) {
            long count = this.sysPermissionMapper.selectCount(new QueryWrapper<SysPermission>().lambda().eq(SysPermission::getParentId, pid));
            if (count == 1) {
                //若父节点无其他子节点，则该父节点是叶子节点
                this.sysPermissionMapper.setMenuLeaf(pid, 1);
            }
        }
        sysPermissionMapper.deleteById(id);
        // 该节点可能是子节点但也可能是其它节点的父节点,所以需要级联删除
        this.removeChildrenBy(sysPermission.getId());
    }

    /**
     * 根据父id删除其关联的子节点数据
     *
     * @return
     */
    public void removeChildrenBy(String parentId) {
        LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<>();
        // 封装查询条件parentId为主键,
        query.eq(SysPermission::getParentId, parentId);
        // 查出该主键下的所有子级
        List<SysPermission> permissionList = this.sysPermissionMapper.selectList(query);
        if (permissionList != null && permissionList.size() > 0) {
            String id = ""; // id
            long num = 0; // 查出的子级数量
            // 如果查出的集合不为空, 则先删除所有
            this.sysPermissionMapper.delete(query);
            // 再遍历刚才查出的集合, 根据每个对象,查找其是否仍有子级
            for (int i = 0, len = permissionList.size(); i < len; i++) {
                id = permissionList.get(i).getId();
                Map map = new HashMap<>();
                map.put("permission_id", id);
                num = this.sysPermissionMapper.selectCount(new LambdaQueryWrapper<SysPermission>().eq(SysPermission::getParentId, id));
                // 如果有, 则递归
                if (num > 0) {
                    this.removeChildrenBy(id);
                }
            }
        }
    }

    public void addPermission(SysPermission sysPermission)  {
        //----------------------------------------------------------------------
        //判断是否是一级菜单，是的话清空父菜单
        if (CommonConstant.MENU_TYPE_0.equals(sysPermission.getMenuType())) {
            sysPermission.setParentId(null);
        }
        //----------------------------------------------------------------------
        String pid = sysPermission.getParentId();
        if (StringUtils.isNotBlank(pid)) {
            //设置父节点不为叶子节点
            this.sysPermissionMapper.setMenuLeaf(pid, 0);
        }
        sysPermission.setCreateTime(new Date());
        sysPermission.setDelFlag(0);
        sysPermission.setLeaf(true);
        this.sysPermissionMapper.insert(sysPermission);
    }

    public void editPermission(SysPermission sysPermission) throws BusinessException {
        SysPermission p = this.sysPermissionMapper.selectById(sysPermission.getId());
        if (p == null) {
            throw new BusinessException(StatusEnum.NOT_FOUND);
        } else {
            sysPermission.setUpdateTime(new Date());
            //----------------------------------------------------------------------
            //Step1.判断是否是一级菜单，是的话清空父菜单ID
            if (CommonConstant.MENU_TYPE_0.equals(sysPermission.getMenuType())) {
                sysPermission.setParentId("");
            }
            //Step2.判断菜单下级是否有菜单，无则设置为叶子节点
            long count = this.sysPermissionMapper.selectCount(new QueryWrapper<SysPermission>().lambda().eq(SysPermission::getParentId, sysPermission.getId()));
            if (count == 0) {
                sysPermission.setLeaf(true);
            }
            //----------------------------------------------------------------------
            this.sysPermissionMapper.updateById(sysPermission);

            //如果当前菜单的父菜单变了，则需要修改新父菜单和老父菜单的，叶子节点状态
            String pid = sysPermission.getParentId();
            if ((StringUtils.isNotEmpty(pid) && !pid.equals(p.getParentId())) || StringUtils.isEmpty(pid) && StringUtils.isNotEmpty(p.getParentId())) {
                //a.设置新的父菜单不为叶子节点
                this.sysPermissionMapper.setMenuLeaf(pid, 0);
                //b.判断老的菜单下是否还有其他子菜单，没有的话则设置为叶子节点
                long cc = this.sysPermissionMapper.selectCount(new QueryWrapper<SysPermission>().lambda().eq(SysPermission::getParentId, p.getParentId()));
                if (cc == 0) {
                    if (StringUtils.isNotEmpty(p.getParentId())) {
                        this.sysPermissionMapper.setMenuLeaf(p.getParentId(), 1);
                    }
                }

            }
        }
    }

    public List<SysPermission> queryByUser() {
        return this.sysPermissionMapper.queryByUser();
    }


    public boolean hasPermission(String username, SysPermission sysPermission) {
        int count = this.sysPermissionMapper.queryCountByUsername(username, sysPermission);
        if (count > 0) {
            return true;
        } else {
            return false;
        }
    }

    public boolean hasPermission(String username, String url) {
        SysPermission sysPermission = new SysPermission();
        sysPermission.setUrl(url);
        int count = this.sysPermissionMapper.queryCountByUsername(username, sysPermission);
        if (count > 0) {
            return true;
        } else {
            return false;
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void saveEmpowerPermission(String permissionIds, String tenantIds) {
        // 判断原来授权，现在授权不在的租户取消菜单
        cancelEmpowerPermission(permissionIds, tenantIds);
        // 授权:新增授权租户菜单
        LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<SysPermission>();
        query.eq(SysPermission::getTenantId, 1);
        query.in(SysPermission::getId, permissionIds);
        List<SysPermission> ls = this.sysPermissionMapper.selectList(query);
        Arrays.stream(tenantIds.split(",")).filter(i -> !i.equals("1"))
                .forEach(item -> {
                    //this.sysPermissionMapper
                    //this.saveBatch(setPermissionTenant(ls, Integer.parseInt(item)));
                });
    }

    private List<SysPermission> setPermissionTenant(List<SysPermission> ls, int tenantId) {
        // 循环两次 第一次设置ID和tenantId 第二次设置pid
        Map<String, String> map = new HashMap<>(16);
        // 需要过滤掉之前针对该租户授权过的菜单
        List<SysPermission> new_ls = new ArrayList<>();
        ls.stream()
                .forEach(p -> {
                    // 是否有数据
                    long index = this.sysPermissionMapper.selectCount(new QueryWrapper<SysPermission>().eq("tenant_id", tenantId).eq("empower_permission_id", p.getId()).eq("del_flag", CommonConstant.DEL_FLAG_0));
                    if (index == 0) {
                        SysPermission permission = new SysPermission();
                        BeanUtils.copyProperties(p, permission);
                        long id = IdWorker.getId();
                        String newId = String.valueOf(id);
                        map.put(p.getId(), newId);
                        permission.setEmpowerPermissionId(p.getId());
                        permission.setId(newId);
                        permission.setTenantId(tenantId);
                        permission.setCreateBy(null);
                        permission.setCreateTime(null);
                        permission.setUpdateBy(null);
                        permission.setUpdateTime(null);
                        new_ls.add(permission);
                    }
                });
        // 获取该租户之前授权的菜单：
        LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<>();
        query.select(SysPermission::getId, SysPermission::getEmpowerPermissionId);
        query.eq(SysPermission::getTenantId, tenantId);
        List<SysPermission> old_menu = this.sysPermissionMapper.selectList(query);
        old_menu.stream().forEach(item -> {
            map.put(item.getEmpowerPermissionId(), item.getId());
        });
        for (SysPermission p : new_ls) {
            String oldPid = p.getParentId();
            if (StringUtils.isNotEmpty(oldPid)) {
                String newPid = map.get(oldPid);
                if (StringUtils.isNotEmpty(newPid)) {
                    p.setParentId(newPid);
                } else {
                    // TODO 一般情况下这个newPid是肯定有值的  如果没有值 说明当前节点的父节点 没有设置为基础路由  那么 需要递归获取 所有父级节点 挨个设置一下即可
                    throw new BusinessException(StatusEnum.NOT_AUTH);
                }
            }
        }
        return new_ls;
    }

    public void cancelEmpowerPermission(String permissionIds, String tenantIds) {
        tenantIds = tenantIds.contains("1,") ? tenantIds : "1," + tenantIds;
        // 管理租户 = 1 不删除菜单
        LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<>();
        query.notIn(SysPermission::getTenantId, Arrays.asList(tenantIds.split(",")));
        query.in(SysPermission::getEmpowerPermissionId, Arrays.asList(permissionIds.split(",")));
        SysPermission sysPermission = new SysPermission();
        sysPermission.setDelFlag(CommonConstant.DEL_FLAG_1);
        this.sysPermissionMapper.update(sysPermission, query);
    }



    public List<SysPermission> queryByUser(String username, String systemType) {
        return this.sysPermissionMapper.queryRoleByUser(username, systemType);
    }



    public List<String> getRole(String username) {
        return sysPermissionMapper.getRoleByUserName(username);
    }
}